
class wordsGetter:
    def __init__(self, filename):
        self.filename = filename
        f = self.fileob = file(filename)
        f.seek(0,2) # seek to end
        self.length = self.lineStart(f.tell()-2)
    def wordAt(self, lineStart, fix=True):
        f = self.fileob
        if fix:
            lineStart = self.lineStart(lineStart)
        f.seek(lineStart)
        line = f.readline()
        result = line.strip().lower()
        #pr "wordAt", (lineStart, result)
        return result
    def getWordsNear(self, word, length=10):
        s = self.wordSeek(word)
        L = []
        f = self.fileob
        f.seek(s)
        for i in xrange(length):
            w = f.readline().strip()
            L.append(w)
        return L
    def wordSeek(self, word, start=0, end=None, verbose=False, count=0):
        if end is None:
            end = self.length
        count += 1
        assert count<30
        mid = (start+end)/2 #self.lineStart((start+end)/2)
        assert start<mid<end
        startword = self.wordAt(start)
        midword = self.wordAt(mid)
        endword = self.wordAt(end)
        if verbose:
            print "wordSeek", (start, startword, mid, midword, end, endword)
        if midword==word or midword==startword or midword==endword:
            return self.lineStart(mid)
        if word>midword:
            return self.wordSeek(word, mid, end, verbose, count)
        if midword>word:
            return self.wordSeek(word, start, mid, verbose, count)
        raise ValueError, "unreachable code"
    def lineStart(self, pos):
        c = None
        f = self.fileob
        while c!="\n" and pos>=0:
            pos -= 1
            if pos>=0:
                f.seek(pos)
                c = f.read(1)
        return pos+1
        
def test(filename="/tmp/words", word="cyclos"):
    W = wordsGetter(filename)
    print "file last line at", W.length
    print "last word is", W.wordAt(W.length)
    s = W.wordSeek(word, verbose=True)
    print "for", word, "found near match", W.wordAt(s)
    print "words near", word, "are", W.getWordsNear(word)

if __name__=="__main__":
    test()
